/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997, 1998, 1999  Sam Lantinga

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Sam Lantinga
    slouken@devolution.com
*/

#include <stdio.h>

#include <SDL/SDL.h>
#include "SDL_blit.h"

/* Function to check the CPU flags */
#define MMX_CPU		0x800000
#ifdef USE_ASMBLIT
#define CPU_Flags()	Hermes_X86_CPU()
#else
#define CPU_Flags()	0L
#endif

/* Functions to blit from N-bit surfaces to other surfaces */

#ifdef USE_ASMBLIT

/* Heheheh, we coerce Hermes into using SDL blit information */
#define X86_ASSEMBLER
#define HermesConverterInterface	SDL_BlitInfo
#define HermesClearInterface		void
#define STACKCALL
typedef Uint32 int32;

#include "HeadMMX.h"
#include "HeadX86.h"

#else

/* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */
#define RGB888_RGB332(dst, src) { \
	dst = (((src)&0x00E00000)>>16)| \
	      (((src)&0x0000E000)>>11)| \
	      (((src)&0x000000C0)>>6); \
}
static void Blit_RGB888_index8(SDL_BlitInfo *info)
{
	int c;
	int width, height;
	Uint32 *src;
	Uint8 *map, *dst;
	int srcskip, dstskip;

	/* Set up some basic variables */
	width = info->d_width;
	height = info->d_height;
	src = (Uint32 *)info->s_pixels;
	srcskip = info->s_skip/4;
	dst = info->d_pixels;
	dstskip = info->d_skip;
	map = info->table;

	if ( map == NULL ) {
		while ( height-- ) {
			for ( c=width/4; c; --c ) {
				/* Pack RGB into 8bit pixel */
				RGB888_RGB332(*dst++, *src);
				++src;
				RGB888_RGB332(*dst++, *src);
				++src;
				RGB888_RGB332(*dst++, *src);
				++src;
				RGB888_RGB332(*dst++, *src);
				++src;
			}
			switch ( width % 4 ) {
				case 3:
					RGB888_RGB332(*dst++, *src);
					++src;
				case 2:
					RGB888_RGB332(*dst++, *src);
					++src;
				case 1:
					RGB888_RGB332(*dst++, *src);
					++src;
			}
			src += srcskip;
			dst += dstskip;
		}
	} else {
		int pixel;

		while ( height-- ) {
			for ( c=width/4; c; --c ) {
				/* Pack RGB into 8bit pixel */
				RGB888_RGB332(pixel, *src);
				*dst++ = map[pixel];
				++src;
				RGB888_RGB332(pixel, *src);
				*dst++ = map[pixel];
				++src;
				RGB888_RGB332(pixel, *src);
				*dst++ = map[pixel];
				++src;
				RGB888_RGB332(pixel, *src);
				*dst++ = map[pixel];
				++src;
			}
			switch ( width % 4 ) {
				case 3:
					RGB888_RGB332(pixel, *src);
					*dst++ = map[pixel];
					++src;
				case 2:
					RGB888_RGB332(pixel, *src);
					*dst++ = map[pixel];
					++src;
				case 1:
					RGB888_RGB332(pixel, *src);
					*dst++ = map[pixel];
					++src;
			}
			src += srcskip;
			dst += dstskip;
		}
	}
}
/* Special optimized blit for RGB 8-8-8 --> RGB 5-5-5 */
#define RGB888_RGB555(dst, src) { \
	*(Uint16 *)(dst) = (((*src)&0x00F80000)>>9)| \
	                   (((*src)&0x0000F800)>>6)| \
	                   (((*src)&0x000000F8)>>3); \
}
#define RGB888_RGB555_TWO(dst, src) { \
	*(Uint32 *)(dst) = (((((src[1])&0x00F80000)>>9)| \
	                     (((src[1])&0x0000F800)>>6)| \
	                     (((src[1])&0x000000F8)>>3))<<16)| \
	                     (((src[0])&0x00F80000)>>9)| \
	                     (((src[0])&0x0000F800)>>6)| \
	                     (((src[0])&0x000000F8)>>3); \
}
static void Blit_RGB888_RGB555(SDL_BlitInfo *info)
{
	int c;
	int width, height;
	Uint32 *src;
	Uint16 *dst;
	int srcskip, dstskip;

	/* Set up some basic variables */
	width = info->d_width;
	height = info->d_height;
	src = (Uint32 *)info->s_pixels;
	srcskip = info->s_skip/4;
	dst = (Uint16 *)info->d_pixels;
	dstskip = info->d_skip/2;

	/* Memory align at 4-byte boundary, if necessary */
	if ( (long)dst & 0x03 ) {
		/* Don't do anything if width is 0 */
		if ( width == 0 ) {
			return;
		}
		--width;

		while ( height-- ) {
			/* Perform copy alignment */
			RGB888_RGB555(dst, src);
			++src;
			++dst;

			/* Copy in 4 pixel chunks */
			for ( c=width/4; c; --c ) {
				RGB888_RGB555_TWO(dst, src);
				src += 2;
				dst += 2;
				RGB888_RGB555_TWO(dst, src);
				src += 2;
				dst += 2;
			}
			/* Get any leftovers */
			switch (width % 4) {
				case 3:
					RGB888_RGB555(dst, src);
					++src;
					++dst;
				case 2:
					RGB888_RGB555_TWO(dst, src);
					src += 2;
					dst += 2;
					break;
				case 1:
					RGB888_RGB555(dst, src);
					++src;
					++dst;
					break;
			}
			src += srcskip;
			dst += dstskip;
		}
	} else { 
		while ( height-- ) {
			/* Copy in 4 pixel chunks */
			for ( c=width/4; c; --c ) {
				RGB888_RGB555_TWO(dst, src);
				src += 2;
				dst += 2;
				RGB888_RGB555_TWO(dst, src);
				src += 2;
				dst += 2;
			}
			/* Get any leftovers */
			switch (width % 4) {
				case 3:
					RGB888_RGB555(dst, src);
					++src;
					++dst;
				case 2:
					RGB888_RGB555_TWO(dst, src);
					src += 2;
					dst += 2;
					break;
				case 1:
					RGB888_RGB555(dst, src);
					++src;
					++dst;
					break;
			}
			src += srcskip;
			dst += dstskip;
		}
	}
}
/* Special optimized blit for RGB 8-8-8 --> RGB 5-6-5 */
#define RGB888_RGB565(dst, src) { \
	*(Uint16 *)(dst) = (((*src)&0x00F80000)>>8)| \
	                   (((*src)&0x0000FC00)>>5)| \
	                   (((*src)&0x000000F8)>>3); \
}
#define RGB888_RGB565_TWO(dst, src) { \
	*(Uint32 *)(dst) = (((((src[1])&0x00F80000)>>8)| \
	                     (((src[1])&0x0000FC00)>>5)| \
	                     (((src[1])&0x000000F8)>>3))<<16)| \
	                     (((src[0])&0x00F80000)>>8)| \
	                     (((src[0])&0x0000FC00)>>5)| \
	                     (((src[0])&0x000000F8)>>3); \
}
static void Blit_RGB888_RGB565(SDL_BlitInfo *info)
{
	int c;
	int width, height;
	Uint32 *src;
	Uint16 *dst;
	int srcskip, dstskip;

	/* Set up some basic variables */
	width = info->d_width;
	height = info->d_height;
	src = (Uint32 *)info->s_pixels;
	srcskip = info->s_skip/4;
	dst = (Uint16 *)info->d_pixels;
	dstskip = info->d_skip/2;

	/* Memory align at 4-byte boundary, if necessary */
	if ( (long)dst & 0x03 ) {
		/* Don't do anything if width is 0 */
		if ( width == 0 ) {
			return;
		}
		--width;

		while ( height-- ) {
			/* Perform copy alignment */
			RGB888_RGB565(dst, src);
			++src;
			++dst;

			/* Copy in 4 pixel chunks */
			for ( c=width/4; c; --c ) {
				RGB888_RGB565_TWO(dst, src);
				src += 2;
				dst += 2;
				RGB888_RGB565_TWO(dst, src);
				src += 2;
				dst += 2;
			}
			/* Get any leftovers */
			switch (width % 4) {
				case 3:
					RGB888_RGB565(dst, src);
					++src;
					++dst;
				case 2:
					RGB888_RGB565_TWO(dst, src);
					src += 2;
					dst += 2;
					break;
				case 1:
					RGB888_RGB565(dst, src);
					++src;
					++dst;
					break;
			}
			src += srcskip;
			dst += dstskip;
		}
	} else { 
		while ( height-- ) {
			/* Copy in 4 pixel chunks */
			for ( c=width/4; c; --c ) {
				RGB888_RGB565_TWO(dst, src);
				src += 2;
				dst += 2;
				RGB888_RGB565_TWO(dst, src);
				src += 2;
				dst += 2;
			}
			/* Get any leftovers */
			switch (width % 4) {
				case 3:
					RGB888_RGB565(dst, src);
					++src;
					++dst;
				case 2:
					RGB888_RGB565_TWO(dst, src);
					src += 2;
					dst += 2;
					break;
				case 1:
					RGB888_RGB565(dst, src);
					++src;
					++dst;
					break;
			}
			src += srcskip;
			dst += dstskip;
		}
	}
}
/* Special optimized blit for RGB 5-5-5 --> RGB 5-6-5 */
#define RGB555_RGB565(dst, src) \
	*dst = (((*src)&0x7FE0)<<1)|((*src)&0x001F)
/* Special optimized blit for RGB 5-6-5 --> RGB 5-5-5 */
#define RGB565_RGB555(dst, src) \
	*dst = (((*src)&0xFFC0)>>1)|((*src)&0x001F)
/* FIXME... actually implement the blitters */
#endif /* USE_ASMBLITTER */


/* Special optimized blit for RGB 5-6-5 --> 32-bit RGB surfaces */
#if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
#define RGB565_32(dst, src) { \
	*dst = map[src[0]*2] + map[src[1]*2+1]; \
}
#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
#define RGB565_32(dst, src) { \
	*dst = map[src[1]*2] + map[src[0]*2+1]; \
}
#endif
static void Blit_RGB565_32(SDL_BlitInfo *info, Uint32 *map)
{
	int c;
	int width, height;
	Uint8 *src;
	Uint32 *dst;
	int srcskip, dstskip;

	/* Set up some basic variables */
	width = info->d_width;
	height = info->d_height;
	src = (Uint8 *)info->s_pixels;
	srcskip = info->s_skip;
	dst = (Uint32 *)info->d_pixels;
	dstskip = info->d_skip/4;

	while ( height-- ) {
		/* Copy in 4 pixel chunks */
		for ( c=width/4; c; --c ) {
			RGB565_32(dst, src);
			src += 2;
			dst += 1;
			RGB565_32(dst, src);
			src += 2;
			dst += 1;
			RGB565_32(dst, src);
			src += 2;
			dst += 1;
			RGB565_32(dst, src);
			src += 2;
			dst += 1;
		}
		/* Get any leftovers */
		switch (width % 4) {
			case 3:
				RGB565_32(dst, src);
				src += 2;
				dst += 1;
			case 2:
				RGB565_32(dst, src);
				src += 2;
				dst += 1;
			case 1:
				RGB565_32(dst, src);
				src += 2;
				dst += 1;
				break;
		}
		src += srcskip;
		dst += dstskip;
	}
}

/* Special optimized blit for RGB 5-6-5 --> RGB 8-8-8 */
static Uint32 RGB565_RGB888_LUT[512] = {
		0x00000000, 0x00000000, 0x00000008, 0x00002000,
		0x00000010, 0x00004000, 0x00000018, 0x00006100,
		0x00000020, 0x00008100, 0x00000029, 0x0000a100,
		0x00000031, 0x0000c200, 0x00000039, 0x0000e200,
		0x00000041, 0x00080000, 0x0000004a, 0x00082000,
		0x00000052, 0x00084000, 0x0000005a, 0x00086100,
		0x00000062, 0x00088100, 0x0000006a, 0x0008a100,
		0x00000073, 0x0008c200, 0x0000007b, 0x0008e200,
		0x00000083, 0x00100000, 0x0000008b, 0x00102000,
		0x00000094, 0x00104000, 0x0000009c, 0x00106100,
		0x000000a4, 0x00108100, 0x000000ac, 0x0010a100,
		0x000000b4, 0x0010c200, 0x000000bd, 0x0010e200,
		0x000000c5, 0x00180000, 0x000000cd, 0x00182000,
		0x000000d5, 0x00184000, 0x000000de, 0x00186100,
		0x000000e6, 0x00188100, 0x000000ee, 0x0018a100,
		0x000000f6, 0x0018c200, 0x000000ff, 0x0018e200,
		0x00000400, 0x00200000, 0x00000408, 0x00202000,
		0x00000410, 0x00204000, 0x00000418, 0x00206100,
		0x00000420, 0x00208100, 0x00000429, 0x0020a100,
		0x00000431, 0x0020c200, 0x00000439, 0x0020e200,
		0x00000441, 0x00290000, 0x0000044a, 0x00292000,
		0x00000452, 0x00294000, 0x0000045a, 0x00296100,
		0x00000462, 0x00298100, 0x0000046a, 0x0029a100,
		0x00000473, 0x0029c200, 0x0000047b, 0x0029e200,
		0x00000483, 0x00310000, 0x0000048b, 0x00312000,
		0x00000494, 0x00314000, 0x0000049c, 0x00316100,
		0x000004a4, 0x00318100, 0x000004ac, 0x0031a100,
		0x000004b4, 0x0031c200, 0x000004bd, 0x0031e200,
		0x000004c5, 0x00390000, 0x000004cd, 0x00392000,
		0x000004d5, 0x00394000, 0x000004de, 0x00396100,
		0x000004e6, 0x00398100, 0x000004ee, 0x0039a100,
		0x000004f6, 0x0039c200, 0x000004ff, 0x0039e200,
		0x00000800, 0x00410000, 0x00000808, 0x00412000,
		0x00000810, 0x00414000, 0x00000818, 0x00416100,
		0x00000820, 0x00418100, 0x00000829, 0x0041a100,
		0x00000831, 0x0041c200, 0x00000839, 0x0041e200,
		0x00000841, 0x004a0000, 0x0000084a, 0x004a2000,
		0x00000852, 0x004a4000, 0x0000085a, 0x004a6100,
		0x00000862, 0x004a8100, 0x0000086a, 0x004aa100,
		0x00000873, 0x004ac200, 0x0000087b, 0x004ae200,
		0x00000883, 0x00520000, 0x0000088b, 0x00522000,
		0x00000894, 0x00524000, 0x0000089c, 0x00526100,
		0x000008a4, 0x00528100, 0x000008ac, 0x0052a100,
		0x000008b4, 0x0052c200, 0x000008bd, 0x0052e200,
		0x000008c5, 0x005a0000, 0x000008cd, 0x005a2000,
		0x000008d5, 0x005a4000, 0x000008de, 0x005a6100,
		0x000008e6, 0x005a8100, 0x000008ee, 0x005aa100,
		0x000008f6, 0x005ac200, 0x000008ff, 0x005ae200,
		0x00000c00, 0x00620000, 0x00000c08, 0x00622000,
		0x00000c10, 0x00624000, 0x00000c18, 0x00626100,
		0x00000c20, 0x00628100, 0x00000c29, 0x0062a100,
		0x00000c31, 0x0062c200, 0x00000c39, 0x0062e200,
		0x00000c41, 0x006a0000, 0x00000c4a, 0x006a2000,
		0x00000c52, 0x006a4000, 0x00000c5a, 0x006a6100,
		0x00000c62, 0x006a8100, 0x00000c6a, 0x006aa100,
		0x00000c73, 0x006ac200, 0x00000c7b, 0x006ae200,
		0x00000c83, 0x00730000, 0x00000c8b, 0x00732000,
		0x00000c94, 0x00734000, 0x00000c9c, 0x00736100,
		0x00000ca4, 0x00738100, 0x00000cac, 0x0073a100,
		0x00000cb4, 0x0073c200, 0x00000cbd, 0x0073e200,
		0x00000cc5, 0x007b0000, 0x00000ccd, 0x007b2000,
		0x00000cd5, 0x007b4000, 0x00000cde, 0x007b6100,
		0x00000ce6, 0x007b8100, 0x00000cee, 0x007ba100,
		0x00000cf6, 0x007bc200, 0x00000cff, 0x007be200,
		0x00001000, 0x00830000, 0x00001008, 0x00832000,
		0x00001010, 0x00834000, 0x00001018, 0x00836100,
		0x00001020, 0x00838100, 0x00001029, 0x0083a100,
		0x00001031, 0x0083c200, 0x00001039, 0x0083e200,
		0x00001041, 0x008b0000, 0x0000104a, 0x008b2000,
		0x00001052, 0x008b4000, 0x0000105a, 0x008b6100,
		0x00001062, 0x008b8100, 0x0000106a, 0x008ba100,
		0x00001073, 0x008bc200, 0x0000107b, 0x008be200,
		0x00001083, 0x00940000, 0x0000108b, 0x00942000,
		0x00001094, 0x00944000, 0x0000109c, 0x00946100,
		0x000010a4, 0x00948100, 0x000010ac, 0x0094a100,
		0x000010b4, 0x0094c200, 0x000010bd, 0x0094e200,
		0x000010c5, 0x009c0000, 0x000010cd, 0x009c2000,
		0x000010d5, 0x009c4000, 0x000010de, 0x009c6100,
		0x000010e6, 0x009c8100, 0x000010ee, 0x009ca100,
		0x000010f6, 0x009cc200, 0x000010ff, 0x009ce200,
		0x00001400, 0x00a40000, 0x00001408, 0x00a42000,
		0x00001410, 0x00a44000, 0x00001418, 0x00a46100,
		0x00001420, 0x00a48100, 0x00001429, 0x00a4a100,
		0x00001431, 0x00a4c200, 0x00001439, 0x00a4e200,
		0x00001441, 0x00ac0000, 0x0000144a, 0x00ac2000,
		0x00001452, 0x00ac4000, 0x0000145a, 0x00ac6100,
		0x00001462, 0x00ac8100, 0x0000146a, 0x00aca100,
		0x00001473, 0x00acc200, 0x0000147b, 0x00ace200,
		0x00001483, 0x00b40000, 0x0000148b, 0x00b42000,
		0x00001494, 0x00b44000, 0x0000149c, 0x00b46100,
		0x000014a4, 0x00b48100, 0x000014ac, 0x00b4a100,
		0x000014b4, 0x00b4c200, 0x000014bd, 0x00b4e200,
		0x000014c5, 0x00bd0000, 0x000014cd, 0x00bd2000,
		0x000014d5, 0x00bd4000, 0x000014de, 0x00bd6100,
		0x000014e6, 0x00bd8100, 0x000014ee, 0x00bda100,
		0x000014f6, 0x00bdc200, 0x000014ff, 0x00bde200,
		0x00001800, 0x00c50000, 0x00001808, 0x00c52000,
		0x00001810, 0x00c54000, 0x00001818, 0x00c56100,
		0x00001820, 0x00c58100, 0x00001829, 0x00c5a100,
		0x00001831, 0x00c5c200, 0x00001839, 0x00c5e200,
		0x00001841, 0x00cd0000, 0x0000184a, 0x00cd2000,
		0x00001852, 0x00cd4000, 0x0000185a, 0x00cd6100,
		0x00001862, 0x00cd8100, 0x0000186a, 0x00cda100,
		0x00001873, 0x00cdc200, 0x0000187b, 0x00cde200,
		0x00001883, 0x00d50000, 0x0000188b, 0x00d52000,
		0x00001894, 0x00d54000, 0x0000189c, 0x00d56100,
		0x000018a4, 0x00d58100, 0x000018ac, 0x00d5a100,
		0x000018b4, 0x00d5c200, 0x000018bd, 0x00d5e200,
		0x000018c5, 0x00de0000, 0x000018cd, 0x00de2000,
		0x000018d5, 0x00de4000, 0x000018de, 0x00de6100,
		0x000018e6, 0x00de8100, 0x000018ee, 0x00dea100,
		0x000018f6, 0x00dec200, 0x000018ff, 0x00dee200,
		0x00001c00, 0x00e60000, 0x00001c08, 0x00e62000,
		0x00001c10, 0x00e64000, 0x00001c18, 0x00e66100,
		0x00001c20, 0x00e68100, 0x00001c29, 0x00e6a100,
		0x00001c31, 0x00e6c200, 0x00001c39, 0x00e6e200,
		0x00001c41, 0x00ee0000, 0x00001c4a, 0x00ee2000,
		0x00001c52, 0x00ee4000, 0x00001c5a, 0x00ee6100,
		0x00001c62, 0x00ee8100, 0x00001c6a, 0x00eea100,
		0x00001c73, 0x00eec200, 0x00001c7b, 0x00eee200,
		0x00001c83, 0x00f60000, 0x00001c8b, 0x00f62000,
		0x00001c94, 0x00f64000, 0x00001c9c, 0x00f66100,
		0x00001ca4, 0x00f68100, 0x00001cac, 0x00f6a100,
		0x00001cb4, 0x00f6c200, 0x00001cbd, 0x00f6e200,
		0x00001cc5, 0x00ff0000, 0x00001ccd, 0x00ff2000,
		0x00001cd5, 0x00ff4000, 0x00001cde, 0x00ff6100,
		0x00001ce6, 0x00ff8100, 0x00001cee, 0x00ffa100,
		0x00001cf6, 0x00ffc200, 0x00001cff, 0x00ffe200
};
static void Blit_RGB565_RGB888(SDL_BlitInfo *info)
{
    Blit_RGB565_32(info, RGB565_RGB888_LUT);
}

/* Special optimized blit for RGB 5-6-5 --> BGR 8-8-8 */
static Uint32 RGB565_BGR888_LUT[512] = {
		0x00000000, 0x00000000, 0x00080000, 0x00002000,
		0x00100000, 0x00004000, 0x00180000, 0x00006100,
		0x00200000, 0x00008100, 0x00290000, 0x0000a100,
		0x00310000, 0x0000c200, 0x00390000, 0x0000e200,
		0x00410000, 0x00000008, 0x004a0000, 0x00002008,
		0x00520000, 0x00004008, 0x005a0000, 0x00006108,
		0x00620000, 0x00008108, 0x006a0000, 0x0000a108,
		0x00730000, 0x0000c208, 0x007b0000, 0x0000e208,
		0x00830000, 0x00000010, 0x008b0000, 0x00002010,
		0x00940000, 0x00004010, 0x009c0000, 0x00006110,
		0x00a40000, 0x00008110, 0x00ac0000, 0x0000a110,
		0x00b40000, 0x0000c210, 0x00bd0000, 0x0000e210,
		0x00c50000, 0x00000018, 0x00cd0000, 0x00002018,
		0x00d50000, 0x00004018, 0x00de0000, 0x00006118,
		0x00e60000, 0x00008118, 0x00ee0000, 0x0000a118,
		0x00f60000, 0x0000c218, 0x00ff0000, 0x0000e218,
		0x00000400, 0x00000020, 0x00080400, 0x00002020,
		0x00100400, 0x00004020, 0x00180400, 0x00006120,
		0x00200400, 0x00008120, 0x00290400, 0x0000a120,
		0x00310400, 0x0000c220, 0x00390400, 0x0000e220,
		0x00410400, 0x00000029, 0x004a0400, 0x00002029,
		0x00520400, 0x00004029, 0x005a0400, 0x00006129,
		0x00620400, 0x00008129, 0x006a0400, 0x0000a129,
		0x00730400, 0x0000c229, 0x007b0400, 0x0000e229,
		0x00830400, 0x00000031, 0x008b0400, 0x00002031,
		0x00940400, 0x00004031, 0x009c0400, 0x00006131,
		0x00a40400, 0x00008131, 0x00ac0400, 0x0000a131,
		0x00b40400, 0x0000c231, 0x00bd0400, 0x0000e231,
		0x00c50400, 0x00000039, 0x00cd0400, 0x00002039,
		0x00d50400, 0x00004039, 0x00de0400, 0x00006139,
		0x00e60400, 0x00008139, 0x00ee0400, 0x0000a139,
		0x00f60400, 0x0000c239, 0x00ff0400, 0x0000e239,
		0x00000800, 0x00000041, 0x00080800, 0x00002041,
		0x00100800, 0x00004041, 0x00180800, 0x00006141,
		0x00200800, 0x00008141, 0x00290800, 0x0000a141,
		0x00310800, 0x0000c241, 0x00390800, 0x0000e241,
		0x00410800, 0x0000004a, 0x004a0800, 0x0000204a,
		0x00520800, 0x0000404a, 0x005a0800, 0x0000614a,
		0x00620800, 0x0000814a, 0x006a0800, 0x0000a14a,
		0x00730800, 0x0000c24a, 0x007b0800, 0x0000e24a,
		0x00830800, 0x00000052, 0x008b0800, 0x00002052,
		0x00940800, 0x00004052, 0x009c0800, 0x00006152,
		0x00a40800, 0x00008152, 0x00ac0800, 0x0000a152,
		0x00b40800, 0x0000c252, 0x00bd0800, 0x0000e252,
		0x00c50800, 0x0000005a, 0x00cd0800, 0x0000205a,
		0x00d50800, 0x0000405a, 0x00de0800, 0x0000615a,
		0x00e60800, 0x0000815a, 0x00ee0800, 0x0000a15a,
		0x00f60800, 0x0000c25a, 0x00ff0800, 0x0000e25a,
		0x00000c00, 0x00000062, 0x00080c00, 0x00002062,
		0x00100c00, 0x00004062, 0x00180c00, 0x00006162,
		0x00200c00, 0x00008162, 0x00290c00, 0x0000a162,
		0x00310c00, 0x0000c262, 0x00390c00, 0x0000e262,
		0x00410c00, 0x0000006a, 0x004a0c00, 0x0000206a,
		0x00520c00, 0x0000406a, 0x005a0c00, 0x0000616a,
		0x00620c00, 0x0000816a, 0x006a0c00, 0x0000a16a,
		0x00730c00, 0x0000c26a, 0x007b0c00, 0x0000e26a,
		0x00830c00, 0x00000073, 0x008b0c00, 0x00002073,
		0x00940c00, 0x00004073, 0x009c0c00, 0x00006173,
		0x00a40c00, 0x00008173, 0x00ac0c00, 0x0000a173,
		0x00b40c00, 0x0000c273, 0x00bd0c00, 0x0000e273,
		0x00c50c00, 0x0000007b, 0x00cd0c00, 0x0000207b,
		0x00d50c00, 0x0000407b, 0x00de0c00, 0x0000617b,
		0x00e60c00, 0x0000817b, 0x00ee0c00, 0x0000a17b,
		0x00f60c00, 0x0000c27b, 0x00ff0c00, 0x0000e27b,
		0x00001000, 0x00000083, 0x00081000, 0x00002083,
		0x00101000, 0x00004083, 0x00181000, 0x00006183,
		0x00201000, 0x00008183, 0x00291000, 0x0000a183,
		0x00311000, 0x0000c283, 0x00391000, 0x0000e283,
		0x00411000, 0x0000008b, 0x004a1000, 0x0000208b,
		0x00521000, 0x0000408b, 0x005a1000, 0x0000618b,
		0x00621000, 0x0000818b, 0x006a1000, 0x0000a18b,
		0x00731000, 0x0000c28b, 0x007b1000, 0x0000e28b,
		0x00831000, 0x00000094, 0x008b1000, 0x00002094,
		0x00941000, 0x00004094, 0x009c1000, 0x00006194,
		0x00a41000, 0x00008194, 0x00ac1000, 0x0000a194,
		0x00b41000, 0x0000c294, 0x00bd1000, 0x0000e294,
		0x00c51000, 0x0000009c, 0x00cd1000, 0x0000209c,
		0x00d51000, 0x0000409c, 0x00de1000, 0x0000619c,
		0x00e61000, 0x0000819c, 0x00ee1000, 0x0000a19c,
		0x00f61000, 0x0000c29c, 0x00ff1000, 0x0000e29c,
		0x00001400, 0x000000a4, 0x00081400, 0x000020a4,
		0x00101400, 0x000040a4, 0x00181400, 0x000061a4,
		0x00201400, 0x000081a4, 0x00291400, 0x0000a1a4,
		0x00311400, 0x0000c2a4, 0x00391400, 0x0000e2a4,
		0x00411400, 0x000000ac, 0x004a1400, 0x000020ac,
		0x00521400, 0x000040ac, 0x005a1400, 0x000061ac,
		0x00621400, 0x000081ac, 0x006a1400, 0x0000a1ac,
		0x00731400, 0x0000c2ac, 0x007b1400, 0x0000e2ac,
		0x00831400, 0x000000b4, 0x008b1400, 0x000020b4,
		0x00941400, 0x000040b4, 0x009c1400, 0x000061b4,
		0x00a41400, 0x000081b4, 0x00ac1400, 0x0000a1b4,
		0x00b41400, 0x0000c2b4, 0x00bd1400, 0x0000e2b4,
		0x00c51400, 0x000000bd, 0x00cd1400, 0x000020bd,
		0x00d51400, 0x000040bd, 0x00de1400, 0x000061bd,
		0x00e61400, 0x000081bd, 0x00ee1400, 0x0000a1bd,
		0x00f61400, 0x0000c2bd, 0x00ff1400, 0x0000e2bd,
		0x00001800, 0x000000c5, 0x00081800, 0x000020c5,
		0x00101800, 0x000040c5, 0x00181800, 0x000061c5,
		0x00201800, 0x000081c5, 0x00291800, 0x0000a1c5,
		0x00311800, 0x0000c2c5, 0x00391800, 0x0000e2c5,
		0x00411800, 0x000000cd, 0x004a1800, 0x000020cd,
		0x00521800, 0x000040cd, 0x005a1800, 0x000061cd,
		0x00621800, 0x000081cd, 0x006a1800, 0x0000a1cd,
		0x00731800, 0x0000c2cd, 0x007b1800, 0x0000e2cd,
		0x00831800, 0x000000d5, 0x008b1800, 0x000020d5,
		0x00941800, 0x000040d5, 0x009c1800, 0x000061d5,
		0x00a41800, 0x000081d5, 0x00ac1800, 0x0000a1d5,
		0x00b41800, 0x0000c2d5, 0x00bd1800, 0x0000e2d5,
		0x00c51800, 0x000000de, 0x00cd1800, 0x000020de,
		0x00d51800, 0x000040de, 0x00de1800, 0x000061de,
		0x00e61800, 0x000081de, 0x00ee1800, 0x0000a1de,
		0x00f61800, 0x0000c2de, 0x00ff1800, 0x0000e2de,
		0x00001c00, 0x000000e6, 0x00081c00, 0x000020e6,
		0x00101c00, 0x000040e6, 0x00181c00, 0x000061e6,
		0x00201c00, 0x000081e6, 0x00291c00, 0x0000a1e6,
		0x00311c00, 0x0000c2e6, 0x00391c00, 0x0000e2e6,
		0x00411c00, 0x000000ee, 0x004a1c00, 0x000020ee,
		0x00521c00, 0x000040ee, 0x005a1c00, 0x000061ee,
		0x00621c00, 0x000081ee, 0x006a1c00, 0x0000a1ee,
		0x00731c00, 0x0000c2ee, 0x007b1c00, 0x0000e2ee,
		0x00831c00, 0x000000f6, 0x008b1c00, 0x000020f6,
		0x00941c00, 0x000040f6, 0x009c1c00, 0x000061f6,
		0x00a41c00, 0x000081f6, 0x00ac1c00, 0x0000a1f6,
		0x00b41c00, 0x0000c2f6, 0x00bd1c00, 0x0000e2f6,
		0x00c51c00, 0x000000ff, 0x00cd1c00, 0x000020ff,
		0x00d51c00, 0x000040ff, 0x00de1c00, 0x000061ff,
		0x00e61c00, 0x000081ff, 0x00ee1c00, 0x0000a1ff,
		0x00f61c00, 0x0000c2ff, 0x00ff1c00, 0x0000e2ff
};
static void Blit_RGB565_BGR888(SDL_BlitInfo *info)
{
    Blit_RGB565_32(info, RGB565_BGR888_LUT);
}

/* Special optimized blit for RGB 5-6-5 --> RGBA 8-8-8-8 */
static Uint32 RGB565_RGBA888_LUT[512] = {
		0x000000ff, 0x000000ff, 0x000008ff, 0x002000ff,
		0x000010ff, 0x004000ff, 0x000018ff, 0x006100ff,
		0x000020ff, 0x008100ff, 0x000029ff, 0x00a100ff,
		0x000031ff, 0x00c200ff, 0x000039ff, 0x00e200ff,
		0x000041ff, 0x080000ff, 0x00004aff, 0x082000ff,
		0x000052ff, 0x084000ff, 0x00005aff, 0x086100ff,
		0x000062ff, 0x088100ff, 0x00006aff, 0x08a100ff,
		0x000073ff, 0x08c200ff, 0x00007bff, 0x08e200ff,
		0x000083ff, 0x100000ff, 0x00008bff, 0x102000ff,
		0x000094ff, 0x104000ff, 0x00009cff, 0x106100ff,
		0x0000a4ff, 0x108100ff, 0x0000acff, 0x10a100ff,
		0x0000b4ff, 0x10c200ff, 0x0000bdff, 0x10e200ff,
		0x0000c5ff, 0x180000ff, 0x0000cdff, 0x182000ff,
		0x0000d5ff, 0x184000ff, 0x0000deff, 0x186100ff,
		0x0000e6ff, 0x188100ff, 0x0000eeff, 0x18a100ff,
		0x0000f6ff, 0x18c200ff, 0x0000ffff, 0x18e200ff,
		0x000400ff, 0x200000ff, 0x000408ff, 0x202000ff,
		0x000410ff, 0x204000ff, 0x000418ff, 0x206100ff,
		0x000420ff, 0x208100ff, 0x000429ff, 0x20a100ff,
		0x000431ff, 0x20c200ff, 0x000439ff, 0x20e200ff,
		0x000441ff, 0x290000ff, 0x00044aff, 0x292000ff,
		0x000452ff, 0x294000ff, 0x00045aff, 0x296100ff,
		0x000462ff, 0x298100ff, 0x00046aff, 0x29a100ff,
		0x000473ff, 0x29c200ff, 0x00047bff, 0x29e200ff,
		0x000483ff, 0x310000ff, 0x00048bff, 0x312000ff,
		0x000494ff, 0x314000ff, 0x00049cff, 0x316100ff,
		0x0004a4ff, 0x318100ff, 0x0004acff, 0x31a100ff,
		0x0004b4ff, 0x31c200ff, 0x0004bdff, 0x31e200ff,
		0x0004c5ff, 0x390000ff, 0x0004cdff, 0x392000ff,
		0x0004d5ff, 0x394000ff, 0x0004deff, 0x396100ff,
		0x0004e6ff, 0x398100ff, 0x0004eeff, 0x39a100ff,
		0x0004f6ff, 0x39c200ff, 0x0004ffff, 0x39e200ff,
		0x000800ff, 0x410000ff, 0x000808ff, 0x412000ff,
		0x000810ff, 0x414000ff, 0x000818ff, 0x416100ff,
		0x000820ff, 0x418100ff, 0x000829ff, 0x41a100ff,
		0x000831ff, 0x41c200ff, 0x000839ff, 0x41e200ff,
		0x000841ff, 0x4a0000ff, 0x00084aff, 0x4a2000ff,
		0x000852ff, 0x4a4000ff, 0x00085aff, 0x4a6100ff,
		0x000862ff, 0x4a8100ff, 0x00086aff, 0x4aa100ff,
		0x000873ff, 0x4ac200ff, 0x00087bff, 0x4ae200ff,
		0x000883ff, 0x520000ff, 0x00088bff, 0x522000ff,
		0x000894ff, 0x524000ff, 0x00089cff, 0x526100ff,
		0x0008a4ff, 0x528100ff, 0x0008acff, 0x52a100ff,
		0x0008b4ff, 0x52c200ff, 0x0008bdff, 0x52e200ff,
		0x0008c5ff, 0x5a0000ff, 0x0008cdff, 0x5a2000ff,
		0x0008d5ff, 0x5a4000ff, 0x0008deff, 0x5a6100ff,
		0x0008e6ff, 0x5a8100ff, 0x0008eeff, 0x5aa100ff,
		0x0008f6ff, 0x5ac200ff, 0x0008ffff, 0x5ae200ff,
		0x000c00ff, 0x620000ff, 0x000c08ff, 0x622000ff,
		0x000c10ff, 0x624000ff, 0x000c18ff, 0x626100ff,
		0x000c20ff, 0x628100ff, 0x000c29ff, 0x62a100ff,
		0x000c31ff, 0x62c200ff, 0x000c39ff, 0x62e200ff,
		0x000c41ff, 0x6a0000ff, 0x000c4aff, 0x6a2000ff,
		0x000c52ff, 0x6a4000ff, 0x000c5aff, 0x6a6100ff,
		0x000c62ff, 0x6a8100ff, 0x000c6aff, 0x6aa100ff,
		0x000c73ff, 0x6ac200ff, 0x000c7bff, 0x6ae200ff,
		0x000c83ff, 0x730000ff, 0x000c8bff, 0x732000ff,
		0x000c94ff, 0x734000ff, 0x000c9cff, 0x736100ff,
		0x000ca4ff, 0x738100ff, 0x000cacff, 0x73a100ff,
		0x000cb4ff, 0x73c200ff, 0x000cbdff, 0x73e200ff,
		0x000cc5ff, 0x7b0000ff, 0x000ccdff, 0x7b2000ff,
		0x000cd5ff, 0x7b4000ff, 0x000cdeff, 0x7b6100ff,
		0x000ce6ff, 0x7b8100ff, 0x000ceeff, 0x7ba100ff,
		0x000cf6ff, 0x7bc200ff, 0x000cffff, 0x7be200ff,
		0x001000ff, 0x830000ff, 0x001008ff, 0x832000ff,
		0x001010ff, 0x834000ff, 0x001018ff, 0x836100ff,
		0x001020ff, 0x838100ff, 0x001029ff, 0x83a100ff,
		0x001031ff, 0x83c200ff, 0x001039ff, 0x83e200ff,
		0x001041ff, 0x8b0000ff, 0x00104aff, 0x8b2000ff,
		0x001052ff, 0x8b4000ff, 0x00105aff, 0x8b6100ff,
		0x001062ff, 0x8b8100ff, 0x00106aff, 0x8ba100ff,
		0x001073ff, 0x8bc200ff, 0x00107bff, 0x8be200ff,
		0x001083ff, 0x940000ff, 0x00108bff, 0x942000ff,
		0x001094ff, 0x944000ff, 0x00109cff, 0x946100ff,
		0x0010a4ff, 0x948100ff, 0x0010acff, 0x94a100ff,
		0x0010b4ff, 0x94c200ff, 0x0010bdff, 0x94e200ff,
		0x0010c5ff, 0x9c0000ff, 0x0010cdff, 0x9c2000ff,
		0x0010d5ff, 0x9c4000ff, 0x0010deff, 0x9c6100ff,
		0x0010e6ff, 0x9c8100ff, 0x0010eeff, 0x9ca100ff,
		0x0010f6ff, 0x9cc200ff, 0x0010ffff, 0x9ce200ff,
		0x001400ff, 0xa40000ff, 0x001408ff, 0xa42000ff,
		0x001410ff, 0xa44000ff, 0x001418ff, 0xa46100ff,
		0x001420ff, 0xa48100ff, 0x001429ff, 0xa4a100ff,
		0x001431ff, 0xa4c200ff, 0x001439ff, 0xa4e200ff,
		0x001441ff, 0xac0000ff, 0x00144aff, 0xac2000ff,
		0x001452ff, 0xac4000ff, 0x00145aff, 0xac6100ff,
		0x001462ff, 0xac8100ff, 0x00146aff, 0xaca100ff,
		0x001473ff, 0xacc200ff, 0x00147bff, 0xace200ff,
		0x001483ff, 0xb40000ff, 0x00148bff, 0xb42000ff,
		0x001494ff, 0xb44000ff, 0x00149cff, 0xb46100ff,
		0x0014a4ff, 0xb48100ff, 0x0014acff, 0xb4a100ff,
		0x0014b4ff, 0xb4c200ff, 0x0014bdff, 0xb4e200ff,
		0x0014c5ff, 0xbd0000ff, 0x0014cdff, 0xbd2000ff,
		0x0014d5ff, 0xbd4000ff, 0x0014deff, 0xbd6100ff,
		0x0014e6ff, 0xbd8100ff, 0x0014eeff, 0xbda100ff,
		0x0014f6ff, 0xbdc200ff, 0x0014ffff, 0xbde200ff,
		0x001800ff, 0xc50000ff, 0x001808ff, 0xc52000ff,
		0x001810ff, 0xc54000ff, 0x001818ff, 0xc56100ff,
		0x001820ff, 0xc58100ff, 0x001829ff, 0xc5a100ff,
		0x001831ff, 0xc5c200ff, 0x001839ff, 0xc5e200ff,
		0x001841ff, 0xcd0000ff, 0x00184aff, 0xcd2000ff,
		0x001852ff, 0xcd4000ff, 0x00185aff, 0xcd6100ff,
		0x001862ff, 0xcd8100ff, 0x00186aff, 0xcda100ff,
		0x001873ff, 0xcdc200ff, 0x00187bff, 0xcde200ff,
		0x001883ff, 0xd50000ff, 0x00188bff, 0xd52000ff,
		0x001894ff, 0xd54000ff, 0x00189cff, 0xd56100ff,
		0x0018a4ff, 0xd58100ff, 0x0018acff, 0xd5a100ff,
		0x0018b4ff, 0xd5c200ff, 0x0018bdff, 0xd5e200ff,
		0x0018c5ff, 0xde0000ff, 0x0018cdff, 0xde2000ff,
		0x0018d5ff, 0xde4000ff, 0x0018deff, 0xde6100ff,
		0x0018e6ff, 0xde8100ff, 0x0018eeff, 0xdea100ff,
		0x0018f6ff, 0xdec200ff, 0x0018ffff, 0xdee200ff,
		0x001c00ff, 0xe60000ff, 0x001c08ff, 0xe62000ff,
		0x001c10ff, 0xe64000ff, 0x001c18ff, 0xe66100ff,
		0x001c20ff, 0xe68100ff, 0x001c29ff, 0xe6a100ff,
		0x001c31ff, 0xe6c200ff, 0x001c39ff, 0xe6e200ff,
		0x001c41ff, 0xee0000ff, 0x001c4aff, 0xee2000ff,
		0x001c52ff, 0xee4000ff, 0x001c5aff, 0xee6100ff,
		0x001c62ff, 0xee8100ff, 0x001c6aff, 0xeea100ff,
		0x001c73ff, 0xeec200ff, 0x001c7bff, 0xeee200ff,
		0x001c83ff, 0xf60000ff, 0x001c8bff, 0xf62000ff,
		0x001c94ff, 0xf64000ff, 0x001c9cff, 0xf66100ff,
		0x001ca4ff, 0xf68100ff, 0x001cacff, 0xf6a100ff,
		0x001cb4ff, 0xf6c200ff, 0x001cbdff, 0xf6e200ff,
		0x001cc5ff, 0xff0000ff, 0x001ccdff, 0xff2000ff,
		0x001cd5ff, 0xff4000ff, 0x001cdeff, 0xff6100ff,
		0x001ce6ff, 0xff8100ff, 0x001ceeff, 0xffa100ff,
		0x001cf6ff, 0xffc200ff, 0x001cffff, 0xffe200ff,
};
static void Blit_RGB565_RGBA888(SDL_BlitInfo *info)
{
    Blit_RGB565_32(info, RGB565_RGBA888_LUT);
}

/* Special optimized blit for RGB 5-6-5 --> BGRA 8-8-8-8 */
static Uint32 RGB565_BGRA888_LUT[512] = {
		0x000000ff, 0x000000ff, 0x080000ff, 0x002000ff,
		0x100000ff, 0x004000ff, 0x180000ff, 0x006100ff,
		0x200000ff, 0x008100ff, 0x290000ff, 0x00a100ff,
		0x310000ff, 0x00c200ff, 0x390000ff, 0x00e200ff,
		0x410000ff, 0x000008ff, 0x4a0000ff, 0x002008ff,
		0x520000ff, 0x004008ff, 0x5a0000ff, 0x006108ff,
		0x620000ff, 0x008108ff, 0x6a0000ff, 0x00a108ff,
		0x730000ff, 0x00c208ff, 0x7b0000ff, 0x00e208ff,
		0x830000ff, 0x000010ff, 0x8b0000ff, 0x002010ff,
		0x940000ff, 0x004010ff, 0x9c0000ff, 0x006110ff,
		0xa40000ff, 0x008110ff, 0xac0000ff, 0x00a110ff,
		0xb40000ff, 0x00c210ff, 0xbd0000ff, 0x00e210ff,
		0xc50000ff, 0x000018ff, 0xcd0000ff, 0x002018ff,
		0xd50000ff, 0x004018ff, 0xde0000ff, 0x006118ff,
		0xe60000ff, 0x008118ff, 0xee0000ff, 0x00a118ff,
		0xf60000ff, 0x00c218ff, 0xff0000ff, 0x00e218ff,
		0x000400ff, 0x000020ff, 0x080400ff, 0x002020ff,
		0x100400ff, 0x004020ff, 0x180400ff, 0x006120ff,
		0x200400ff, 0x008120ff, 0x290400ff, 0x00a120ff,
		0x310400ff, 0x00c220ff, 0x390400ff, 0x00e220ff,
		0x410400ff, 0x000029ff, 0x4a0400ff, 0x002029ff,
		0x520400ff, 0x004029ff, 0x5a0400ff, 0x006129ff,
		0x620400ff, 0x008129ff, 0x6a0400ff, 0x00a129ff,
		0x730400ff, 0x00c229ff, 0x7b0400ff, 0x00e229ff,
		0x830400ff, 0x000031ff, 0x8b0400ff, 0x002031ff,
		0x940400ff, 0x004031ff, 0x9c0400ff, 0x006131ff,
		0xa40400ff, 0x008131ff, 0xac0400ff, 0x00a131ff,
		0xb40400ff, 0x00c231ff, 0xbd0400ff, 0x00e231ff,
		0xc50400ff, 0x000039ff, 0xcd0400ff, 0x002039ff,
		0xd50400ff, 0x004039ff, 0xde0400ff, 0x006139ff,
		0xe60400ff, 0x008139ff, 0xee0400ff, 0x00a139ff,
		0xf60400ff, 0x00c239ff, 0xff0400ff, 0x00e239ff,
		0x000800ff, 0x000041ff, 0x080800ff, 0x002041ff,
		0x100800ff, 0x004041ff, 0x180800ff, 0x006141ff,
		0x200800ff, 0x008141ff, 0x290800ff, 0x00a141ff,
		0x310800ff, 0x00c241ff, 0x390800ff, 0x00e241ff,
		0x410800ff, 0x00004aff, 0x4a0800ff, 0x00204aff,
		0x520800ff, 0x00404aff, 0x5a0800ff, 0x00614aff,
		0x620800ff, 0x00814aff, 0x6a0800ff, 0x00a14aff,
		0x730800ff, 0x00c24aff, 0x7b0800ff, 0x00e24aff,
		0x830800ff, 0x000052ff, 0x8b0800ff, 0x002052ff,
		0x940800ff, 0x004052ff, 0x9c0800ff, 0x006152ff,
		0xa40800ff, 0x008152ff, 0xac0800ff, 0x00a152ff,
		0xb40800ff, 0x00c252ff, 0xbd0800ff, 0x00e252ff,
		0xc50800ff, 0x00005aff, 0xcd0800ff, 0x00205aff,
		0xd50800ff, 0x00405aff, 0xde0800ff, 0x00615aff,
		0xe60800ff, 0x00815aff, 0xee0800ff, 0x00a15aff,
		0xf60800ff, 0x00c25aff, 0xff0800ff, 0x00e25aff,
		0x000c00ff, 0x000062ff, 0x080c00ff, 0x002062ff,
		0x100c00ff, 0x004062ff, 0x180c00ff, 0x006162ff,
		0x200c00ff, 0x008162ff, 0x290c00ff, 0x00a162ff,
		0x310c00ff, 0x00c262ff, 0x390c00ff, 0x00e262ff,
		0x410c00ff, 0x00006aff, 0x4a0c00ff, 0x00206aff,
		0x520c00ff, 0x00406aff, 0x5a0c00ff, 0x00616aff,
		0x620c00ff, 0x00816aff, 0x6a0c00ff, 0x00a16aff,
		0x730c00ff, 0x00c26aff, 0x7b0c00ff, 0x00e26aff,
		0x830c00ff, 0x000073ff, 0x8b0c00ff, 0x002073ff,
		0x940c00ff, 0x004073ff, 0x9c0c00ff, 0x006173ff,
		0xa40c00ff, 0x008173ff, 0xac0c00ff, 0x00a173ff,
		0xb40c00ff, 0x00c273ff, 0xbd0c00ff, 0x00e273ff,
		0xc50c00ff, 0x00007bff, 0xcd0c00ff, 0x00207bff,
		0xd50c00ff, 0x00407bff, 0xde0c00ff, 0x00617bff,
		0xe60c00ff, 0x00817bff, 0xee0c00ff, 0x00a17bff,
		0xf60c00ff, 0x00c27bff, 0xff0c00ff, 0x00e27bff,
		0x001000ff, 0x000083ff, 0x081000ff, 0x002083ff,
		0x101000ff, 0x004083ff, 0x181000ff, 0x006183ff,
		0x201000ff, 0x008183ff, 0x291000ff, 0x00a183ff,
		0x311000ff, 0x00c283ff, 0x391000ff, 0x00e283ff,
		0x411000ff, 0x00008bff, 0x4a1000ff, 0x00208bff,
		0x521000ff, 0x00408bff, 0x5a1000ff, 0x00618bff,
		0x621000ff, 0x00818bff, 0x6a1000ff, 0x00a18bff,
		0x731000ff, 0x00c28bff, 0x7b1000ff, 0x00e28bff,
		0x831000ff, 0x000094ff, 0x8b1000ff, 0x002094ff,
		0x941000ff, 0x004094ff, 0x9c1000ff, 0x006194ff,
		0xa41000ff, 0x008194ff, 0xac1000ff, 0x00a194ff,
		0xb41000ff, 0x00c294ff, 0xbd1000ff, 0x00e294ff,
		0xc51000ff, 0x00009cff, 0xcd1000ff, 0x00209cff,
		0xd51000ff, 0x00409cff, 0xde1000ff, 0x00619cff,
		0xe61000ff, 0x00819cff, 0xee1000ff, 0x00a19cff,
		0xf61000ff, 0x00c29cff, 0xff1000ff, 0x00e29cff,
		0x001400ff, 0x0000a4ff, 0x081400ff, 0x0020a4ff,
		0x101400ff, 0x0040a4ff, 0x181400ff, 0x0061a4ff,
		0x201400ff, 0x0081a4ff, 0x291400ff, 0x00a1a4ff,
		0x311400ff, 0x00c2a4ff, 0x391400ff, 0x00e2a4ff,
		0x411400ff, 0x0000acff, 0x4a1400ff, 0x0020acff,
		0x521400ff, 0x0040acff, 0x5a1400ff, 0x0061acff,
		0x621400ff, 0x0081acff, 0x6a1400ff, 0x00a1acff,
		0x731400ff, 0x00c2acff, 0x7b1400ff, 0x00e2acff,
		0x831400ff, 0x0000b4ff, 0x8b1400ff, 0x0020b4ff,
		0x941400ff, 0x0040b4ff, 0x9c1400ff, 0x0061b4ff,
		0xa41400ff, 0x0081b4ff, 0xac1400ff, 0x00a1b4ff,
		0xb41400ff, 0x00c2b4ff, 0xbd1400ff, 0x00e2b4ff,
		0xc51400ff, 0x0000bdff, 0xcd1400ff, 0x0020bdff,
		0xd51400ff, 0x0040bdff, 0xde1400ff, 0x0061bdff,
		0xe61400ff, 0x0081bdff, 0xee1400ff, 0x00a1bdff,
		0xf61400ff, 0x00c2bdff, 0xff1400ff, 0x00e2bdff,
		0x001800ff, 0x0000c5ff, 0x081800ff, 0x0020c5ff,
		0x101800ff, 0x0040c5ff, 0x181800ff, 0x0061c5ff,
		0x201800ff, 0x0081c5ff, 0x291800ff, 0x00a1c5ff,
		0x311800ff, 0x00c2c5ff, 0x391800ff, 0x00e2c5ff,
		0x411800ff, 0x0000cdff, 0x4a1800ff, 0x0020cdff,
		0x521800ff, 0x0040cdff, 0x5a1800ff, 0x0061cdff,
		0x621800ff, 0x0081cdff, 0x6a1800ff, 0x00a1cdff,
		0x731800ff, 0x00c2cdff, 0x7b1800ff, 0x00e2cdff,
		0x831800ff, 0x0000d5ff, 0x8b1800ff, 0x0020d5ff,
		0x941800ff, 0x0040d5ff, 0x9c1800ff, 0x0061d5ff,
		0xa41800ff, 0x0081d5ff, 0xac1800ff, 0x00a1d5ff,
		0xb41800ff, 0x00c2d5ff, 0xbd1800ff, 0x00e2d5ff,
		0xc51800ff, 0x0000deff, 0xcd1800ff, 0x0020deff,
		0xd51800ff, 0x0040deff, 0xde1800ff, 0x0061deff,
		0xe61800ff, 0x0081deff, 0xee1800ff, 0x00a1deff,
		0xf61800ff, 0x00c2deff, 0xff1800ff, 0x00e2deff,
		0x001c00ff, 0x0000e6ff, 0x081c00ff, 0x0020e6ff,
		0x101c00ff, 0x0040e6ff, 0x181c00ff, 0x0061e6ff,
		0x201c00ff, 0x0081e6ff, 0x291c00ff, 0x00a1e6ff,
		0x311c00ff, 0x00c2e6ff, 0x391c00ff, 0x00e2e6ff,
		0x411c00ff, 0x0000eeff, 0x4a1c00ff, 0x0020eeff,
		0x521c00ff, 0x0040eeff, 0x5a1c00ff, 0x0061eeff,
		0x621c00ff, 0x0081eeff, 0x6a1c00ff, 0x00a1eeff,
		0x731c00ff, 0x00c2eeff, 0x7b1c00ff, 0x00e2eeff,
		0x831c00ff, 0x0000f6ff, 0x8b1c00ff, 0x0020f6ff,
		0x941c00ff, 0x0040f6ff, 0x9c1c00ff, 0x0061f6ff,
		0xa41c00ff, 0x0081f6ff, 0xac1c00ff, 0x00a1f6ff,
		0xb41c00ff, 0x00c2f6ff, 0xbd1c00ff, 0x00e2f6ff,
		0xc51c00ff, 0x0000ffff, 0xcd1c00ff, 0x0020ffff,
		0xd51c00ff, 0x0040ffff, 0xde1c00ff, 0x0061ffff,
		0xe61c00ff, 0x0081ffff, 0xee1c00ff, 0x00a1ffff,
		0xf61c00ff, 0x00c2ffff, 0xff1c00ff, 0x00e2ffff
};
static void Blit_RGB565_BGRA888(SDL_BlitInfo *info)
{
    Blit_RGB565_32(info, RGB565_BGRA888_LUT);
}

/* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */
#ifndef RGB888_RGB332
#define RGB888_RGB332(dst, src) { \
	dst = (((src)&0x00E00000)>>16)| \
	      (((src)&0x0000E000)>>11)| \
	      (((src)&0x000000C0)>>6); \
}
#endif
static void Blit_RGB888_index8_map(SDL_BlitInfo *info)
{
	int c, pixel;
	int width, height;
	Uint32 *src;
	Uint8 *map, *dst;
	int srcskip, dstskip;

	/* Set up some basic variables */
	width = info->d_width;
	height = info->d_height;
	src = (Uint32 *)info->s_pixels;
	srcskip = info->s_skip/4;
	dst = info->d_pixels;
	dstskip = info->d_skip;
	map = info->table;

	while ( height-- ) {
		for ( c=width/4; c; --c ) {
			/* Pack RGB into 8bit pixel */
			RGB888_RGB332(pixel, *src);
			*dst++ = map[pixel];
			++src;
			RGB888_RGB332(pixel, *src);
			*dst++ = map[pixel];
			++src;
			RGB888_RGB332(pixel, *src);
			*dst++ = map[pixel];
			++src;
			RGB888_RGB332(pixel, *src);
			*dst++ = map[pixel];
			++src;
		}
		switch ( width % 4 ) {
			case 3:
				RGB888_RGB332(pixel, *src);
				*dst++ = map[pixel];
				++src;
			case 2:
				RGB888_RGB332(pixel, *src);
				*dst++ = map[pixel];
				++src;
			case 1:
				RGB888_RGB332(pixel, *src);
				*dst++ = map[pixel];
				++src;
		}
		src += srcskip;
		dst += dstskip;
	}
}
static void SDL_BlitNto1(SDL_BlitInfo *info)
{
	int c;
	int width, height;
	Uint8 *src, *map, *dst;
	int srcskip, dstskip;
	Uint8 srcbpp;
	Uint32 pixel;
	Uint8  sR, sG, sB;
	SDL_PixelFormat *srcfmt;

	/* Set up some basic variables */
	width = info->d_width;
	height = info->d_height;
	src = info->s_pixels;
	srcskip = info->s_skip;
	dst = info->d_pixels;
	dstskip = info->d_skip;
	map = info->table;
	srcfmt = info->src;
	srcbpp = srcfmt->BytesPerPixel;

	if ( map == NULL ) {
		while ( height-- ) {
			for ( c=width; c; --c ) {
				DISEMBLE_RGB(src, srcbpp, srcfmt, pixel,
								sR, sG, sB);
				if ( 1 ) {
				  	/* Pack RGB into 8bit pixel */
				  	*dst = ((sR>>5)<<(3+2))|
						((sG>>5)<<(2)) |
						((sB>>6)<<(0)) ;
				}
				dst++;
				src += srcbpp;
			}
			src += srcskip;
			dst += dstskip;
		}
	} else {
		while ( height-- ) {
			for ( c=width; c; --c ) {
				DISEMBLE_RGB(src, srcbpp, srcfmt, pixel,
								sR, sG, sB);
				if ( 1 ) {
				  	/* Pack RGB into 8bit pixel */
				  	*dst = map[((sR>>5)<<(3+2))|
						   ((sG>>5)<<(2))  |
						   ((sB>>6)<<(0))  ];
				}
				dst++;
				src += srcbpp;
			}
			src += srcskip;
			dst += dstskip;
		}
	}
}
static void SDL_BlitNtoN(SDL_BlitInfo *info)
{
	int c;
	int width, height;
	Uint8 *src, *dst;
	Uint8 srcbpp;
	Uint8 dstbpp;
	int srcskip, dstskip;
	Uint32 pixel;
	Uint8  sR, sG, sB;
	SDL_PixelFormat *srcfmt;
	SDL_PixelFormat *dstfmt;

	/* Set up some basic variables */
	width = info->d_width;
	height = info->d_height;
	src = info->s_pixels;
	srcskip = info->s_skip;
	dst = info->d_pixels;
	dstskip = info->d_skip;
	srcfmt = info->src;
	srcbpp = srcfmt->BytesPerPixel;
	dstfmt = info->dst;
	dstbpp = dstfmt->BytesPerPixel;

	while ( height-- ) {
		for ( c=width; c; --c ) {
			DISEMBLE_RGB(src, srcbpp, srcfmt, pixel, sR, sG, sB);
			if ( 1 ) {
				  ASSEMBLE_RGB(dst, dstbpp, dstfmt, sR, sG, sB);
			}
			dst += dstbpp;
			src += srcbpp;
		}
		src += srcskip;
		dst += dstskip;
	}
}

static SDL_loblit complex_blit[] = {
	NULL, SDL_BlitKey, SDL_BlitAlpha, SDL_BlitAlphaKey
};

/* Normal N to N optimized blitters */
struct blit_table {
	Uint32 srcR, srcG, srcB;
	int dstbpp;
	Uint32 dstR, dstG, dstB;
	Uint32 cpu_flags;
	void *aux_data;
	SDL_loblit blitfunc;
};
static struct blit_table normal_blit_1[] = {
	/* Default for 8-bit RGB source, an invalid combination */
	{ 0,0,0, 0, 0,0,0, 0, NULL, NULL },
};
static struct blit_table normal_blit_2[] = {
#ifdef USE_ASMBLIT
	{ 0x0000F800,0x000007E0,0x0000001F, 2, 0x0000001F,0x000007E0,0x0000F800,
		 0, ConvertX86p16_16BGR565, ConvertX86 },
	{ 0x0000F800,0x000007E0,0x0000001F, 2, 0x00007C00,0x000003E0,0x0000001F,
		 0, ConvertX86p16_16RGB555, ConvertX86 },
	{ 0x0000F800,0x000007E0,0x0000001F, 2, 0x0000001F,0x000003E0,0x00007C00,
		 0, ConvertX86p16_16BGR555, ConvertX86 },
#endif
	{ 0x0000F800,0x000007E0,0x0000001F, 4, 0x00FF0000,0x0000FF00,0x000000FF,
		 0, NULL, Blit_RGB565_RGB888 },
	{ 0x0000F800,0x000007E0,0x0000001F, 4, 0x000000FF,0x0000FF00,0x00FF0000,
		 0, NULL, Blit_RGB565_BGR888 },
	{ 0x0000F800,0x000007E0,0x0000001F, 4, 0xFF000000,0x00FF0000,0x0000FF00,
		 0, NULL, Blit_RGB565_RGBA888 },
	{ 0x0000F800,0x000007E0,0x0000001F, 4, 0x0000FF00,0x00FF0000,0xFF000000,
		 0, NULL, Blit_RGB565_BGRA888 },

	/* Default for 16-bit RGB source, used if no other blitter matches */
	{ 0,0,0, 0, 0,0,0, 0, NULL, SDL_BlitNtoN },
};
static struct blit_table normal_blit_3[] = {
	/* Default for 24-bit RGB source, never optimized */
	{ 0,0,0, 0, 0,0,0, 0, NULL, SDL_BlitNtoN },
};
static struct blit_table normal_blit_4[] = {
#ifdef USE_ASMBLIT
	{ 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F,
		 0, ConvertX86p32_16RGB565, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000007E0,0x0000F800,
		 0, ConvertX86p32_16BGR565, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F,
		 MMX_CPU, ConvertMMXp32_16RGB555, ConvertMMX },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F,
		 0, ConvertX86p32_16RGB555, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000003E0,0x00007C00,
		 0, ConvertX86p32_16BGR555, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x00FF0000,0x0000FF00,0x000000FF,
		 0, ConvertX86p32_24RGB888, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x000000FF,0x0000FF00,0x00FF0000,
		 0, ConvertX86p32_24BGR888, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 4, 0x000000FF,0x0000FF00,0x00FF0000,
		 0, ConvertX86p32_32BGR888, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 4, 0xFF000000,0x00FF0000,0x0000FF00,
		 0, ConvertX86p32_32RGBA888, ConvertX86 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 4, 0x0000FF00,0x00FF0000,0xFF000000,
		 0, ConvertX86p32_32BGRA888, ConvertX86 },
#else
	{ 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F,
		 0, NULL, Blit_RGB888_RGB565 },
	{ 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F,
		 0, NULL, Blit_RGB888_RGB555 },
#endif
	/* Default for 32-bit RGB source, used if no other blitter matches */
	{ 0,0,0, 0, 0,0,0, 0, NULL, SDL_BlitNtoN },
};
static struct blit_table *normal_blit[] = {
	normal_blit_1, normal_blit_2, normal_blit_3, normal_blit_4
};

SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex)
{
	struct private_swaccel *sdata;
	SDL_PixelFormat *srcfmt;
	SDL_PixelFormat *dstfmt;
	struct blit_table *table;
	int which;
	SDL_loblit blitfun;

	/* Set up data for choosing the blit */
	sdata = surface->map->sw_data;
	srcfmt = surface->format;
	dstfmt = surface->map->dst->format;

	/* Complex are easy to choose, but slow */
	if ( complex ) {
		return(complex_blit[complex]);
	}

	/* We don't support destinations less than 8-bits */
	if ( dstfmt->BitsPerPixel < 8 ) {
		return(NULL);
	}

	blitfun = NULL;
	if ( dstfmt->BitsPerPixel == 8 ) {
		/* We assume 8-bit destinations are palettized */
		if ( (srcfmt->BytesPerPixel == 4) &&
		     (srcfmt->Rmask == 0x00FF0000) &&
		     (srcfmt->Gmask == 0x0000FF00) &&
		     (srcfmt->Bmask == 0x000000FF) ) {
			if ( surface->map->table ) {
				blitfun = Blit_RGB888_index8_map;
			} else {
#ifdef USE_ASMBLIT
				sdata->aux_data = ConvertX86p32_8RGB332;
				blitfun = ConvertX86;
#else
				blitfun = Blit_RGB888_index8;
#endif
			}
		} else {
			blitfun = SDL_BlitNto1;
		}
	} else {
		/* Now the meat, choose the blitter we want */
		table = normal_blit[srcfmt->BytesPerPixel-1];
		for ( which=0; table[which].srcR; ++which ) {
			if ( (srcfmt->Rmask == table[which].srcR) &&
			     (srcfmt->Gmask == table[which].srcG) &&
			     (srcfmt->Bmask == table[which].srcB) &&
			     (dstfmt->BytesPerPixel == table[which].dstbpp) &&
			     (dstfmt->Rmask == table[which].dstR) &&
			     (dstfmt->Gmask == table[which].dstG) &&
			     (dstfmt->Bmask == table[which].dstB) ) {
				if ( (CPU_Flags()&table[which].cpu_flags) ==
						table[which].cpu_flags ) {
					break;
				}
			}
		}
		sdata->aux_data = table[which].aux_data;
		blitfun = table[which].blitfunc;
	}

#ifdef DEBUG_ASM
#ifdef USE_ASMBLIT
	if ( blitfun == ConvertMMX )
		fprintf(stderr, "Using mmx blit\n");
	else
	if ( blitfun == ConvertX86 )
		fprintf(stderr, "Using asm blit\n");
	else
#endif
	if ( (blitfun == SDL_BlitNtoN) || (blitfun == SDL_BlitNto1) )
		fprintf(stderr, "Using C blit\n");
	else
		fprintf(stderr, "Using optimized C blit\n");
#endif /* DEBUG_ASM */

	return(blitfun);
}
